/**
 * @description 全局配置
 */
const dir = "./plugins/BackPackSort";//目录
const configFile = "./plugins/BackPackSort/config.json";//基础配置
const dataFile = "./plugins/BackPackSort/data.json";//玩家数据
const playerData = {};
const config = {
    "priorityGroupMAX": 6,
    "defaultConfig": {
        "itemStore": {},
        "groups": {
            "默认配置": {
                "name": "默认配置",
                "autoStack": true,
                "mainInventory": false,
                "itemPriority": []
            }
        }
    },
    "stackLimit": {
        //无法堆叠的大类
        "unStackClass": [
            "_sword",//剑
            "_pickaxe",//稿子
            "_hoe",//锄头
            "_shovel",//铲子
            "_axe",//斧头
            "_armor",//铠甲
            "_helmet",//头盔
            "_chestplate",//胸甲
            "_leggings",//腿甲
            "_boots",//靴子
            "potion",//药水
            "shulker_box",//潜影盒
            "banner_pattern",//旗帜以及旗帜图案
            "music_disc",//唱片
            "minecart",//矿车
            "_stew",//煲类
            "boat"//船
        ],
        //无法堆叠的物品
        "unStackItems": [
            "minecraft:trident",//三叉戟
            "minecraft:shield",//盾牌
            "minecraft:fishing_rod",//钓竿
            "minecraft:carrot_on_a_stick",//胡萝卜钓竿
            "minecraft:warped_fungus_on_a_stick",//诡异菌菇钓竿
            "minecraft:saddle",//鞍
            "minecraft:elytra",//鞘翅
            "minecraft:totem_of_undying",//不死图腾
            "minecraft:spyglass",//望远镜
            "minecraft:shears",//剪刀
            "minecraft:flint_and_steel",//打火机
            "minecraft:bow",//弓
            "minecraft:crossbow",//弩
            "minecraft:water_bucket",//水桶
            "minecraft:lava_bucket",//岩浆桶
            "minecraft:axolotl_bucket",//美西螈桶
            "minecraft:powder_snow_bucket",//细雪桶
            "minecraft:pufferfish_bucket",//鱼桶
            "minecraft:tropical_fish_bucket",//鱼桶
            "minecraft:salmon_bucket",//鱼桶
            "minecraft:cod_bucket",//鱼桶
            "minecraft:bed",//床
            "minecraft:filled_map",//已生成的地图
            "minecraft:enchanted_book",//附魔书
            "minecraft:beetroot_soup",//甜菜根汤
            "minecraft:milk_bucket",//甜菜根汤
            "minecraft:writable_book",//书与笔
            "minecraft:written_book",//签名后的书


        ],
        //只能堆叠16个的物品
        "Stack16Items": [
            "minecraft:snowball",//雪球
            "minecraft:bucket",//空桶
            "minecraft:honey_bottle",//蜂蜜瓶
            "minecraft:egg",//鸡蛋
            "minecraft:ender_pearl",//末影之眼
            "minecraft:oak_sign",//9种告示牌
            "minecraft:spruce_sign",
            "minecraft:spruce_sign",
            "minecraft:birch_sign",
            "minecraft:jungle_sign",
            "minecraft:acacia_sign",
            "minecraft:dark_oak_sign",
            "minecraft:crimson_sign",
            "minecraft:warped_sign",
            "minecraft:banner",
        ],
    }

}


/**
 * @description 全局变量
 */

let Global = {};

/**
 * @description 文件IO
 */
function init() {
    if (!file.exists(dir))
        file.mkdir(dir);
    if (!file.exists(configFile))
        file.writeTo(configFile, JSON.stringify(config));
    if (!file.exists(dataFile))
        file.writeTo(dataFile, JSON.stringify(playerData));
}

function load(address) {//读取文件
    let data = file.readFrom(address);
    if (data)
        return JSON.parse(data);
    return null;
}

function save(address, obj) {//写入文件
    file.writeTo(address, JSON.stringify(obj));
}

/**
 * @description 表单页面构建
 */
function createMainMenuFm() {//主菜单表单
    let fm = mc.newSimpleForm();
    fm = fm.setTitle("§l物品整理");
    fm = fm.addButton("个人配置");
    fm = fm.addButton("背包整理");
    // fm = fm.addButton("箱子整理");
    fm = fm.addButton("物品仓库");
    return fm;
}

function createConfigFm(pl) {//个人配置表单
    let groups = getPlayerData(pl)["groups"];
    let fm = mc.newSimpleForm();
    fm.setTitle("§l个人配置")

    if (groups) {
        let keyList = Object.keys(groups);
        for (let i = 0; i < keyList.length; i++)
            fm = fm.addButton(keyList[i]);
        fm = fm.addButton("创建配置");
        fm = fm.addButton("删除配置");
    } else {
        fm = fm.setContent("§4玩家数据读取异常!")
    }

    return fm;
}

function createGlobalItemStoreFm() {//物品仓库表单
    let fm = mc.newSimpleForm();
    fm = fm.setTitle("§l物品仓库");
    fm = fm.addButton("添加物品");
    fm = fm.addButton("删除物品");
    fm = fm.addButton("查看物品");
    return fm;
}

function createGlobalItemStoreAddFm(pl) {//物品仓库添加物品表单
    let fm = mc.newCustomForm();
    fm = fm.setTitle("§l添加物品");
    fm = fm.addInput(`输入当前手中物品的名称,${isPersonalGlobalType(pl) ? "添加后会同步至仓库中。" : ""}`, "§4输入不能为空!");
    return fm;
}

function createGlobalItemStoreDeleteFm(pl, store) {//删除物品仓库内物品表单
    let fm = mc.newCustomForm();
    fm = fm.setTitle(isPersonalGlobalType(pl) ? "§l导入物品" : "§l删除物品");
    let nameList = getItemStoreCnNameList(store);
    nameList.forEach((name) => {
        fm = fm.addSwitch(name, false);
    })
    return fm;
}

function createGlobalItemStoreViewFm(store) {//查看物品仓库内物品表单
    let fm = mc.newSimpleForm();
    let list = getItemStoreCnNameList(store);
    let content = `当前仓库中有${list.length}个物品:\n`;
    list.forEach((name) => {
        content += name + " , ";
    })
    fm = fm.setTitle("§l查看物品");
    fm = fm.setContent(content);
    return fm;
}


function createGroupMenuFm(pl) {//优先组菜单表单
    let fm = mc.newSimpleForm();
    fm = fm.setTitle("§l" + Global[pl.xuid].globalGroupName);
    fm = fm.addButton("修改配置");
    fm = fm.addButton("添加物品");
    fm = fm.addButton("删除物品");
    fm = fm.addButton("查看物品");
    return fm;
}

function createUpdateGroupFm(pl, group) {//修改优先组配置的表单
    let fm = mc.newCustomForm();
    fm = fm.setTitle(group["name"]);
    fm = fm.addSwitch("是否自动堆叠", group["autoStack"]);
    fm = fm.addSwitch("是否整理主物品栏", group["mainInventory"]);
    let cnList = getGroupItemCnNameList(pl, Global[pl.xuid].globalGroupName);
    for (let i = 0; i < cnList.length; i++) {
        fm = fm.addDropdown(`第${i}优先级`, cnList, i);
    }
    return fm;
}

function createAddGroupFm(title) {//创建新优先组表单
    let fm = mc.newCustomForm();
    fm = fm.setTitle("§l" + title)
    fm = fm.addInput("输入要创建配置的名称,不输入会自动生成名称");
    return fm;
}

function createDeleteGroupFm(groups) {//创建删除优先组表单
    let fm = mc.newCustomForm();
    fm = fm.setTitle("§l删除配置");
    fm = fm.addLabel("选择你要删除的配置组,可删除多个");
    groups.forEach((groupName) => {
        fm = fm.addSwitch(groupName, false);
    })
    return fm;
}

function createAddGroupItemFm() {//创建优先组添加物品表单
    let fm = mc.newSimpleForm();
    fm = fm.setTitle("§l" + "添加物品");
    fm = fm.addButton("从手中添加");
    fm = fm.addButton("从仓库导入");
    return fm;
}

function createDeleteGroupItemFm(list, store) {//创建删除优先组物品表单
    let fm = mc.newCustomForm();
    fm = fm.setTitle("§l删除物品");
    list.forEach((key) => {
        fm = fm.addSwitch(store[key]["cn"], false);
    })
    return fm;
}

function createChooseSortGroupFm(pl) {
    let fm = mc.newCustomForm();
    fm = fm.setTitle("§l背包整理");
    let groupList = getGroupKeysFromPlayer(pl);
    if (groupList) {
        fm = fm.addDropdown("选择你要使用的整理策略", groupList, 0);
    } else {
        fm = fm.addLabel("§4策略组加载异常!");
    }
    return fm;
}


/**
 * @description 打包好的表单
 */
function sendMainMenuFm(pl) {//发送主菜单
    pl.sendForm(createMainMenuFm(), MenuChoose);
}

function sendPersonalConfigFm(pl) {//发送个人配置的表单
    pl.sendForm(createConfigFm(pl), personalConfigChoose);
}

function sendGlobalItemStoreFm(pl) {//发送物品仓库表单
    pl.sendForm(createGlobalItemStoreFm(), globalItemStoreMenuChoose)
}

function sendGlobalItemStoreAddFm(pl) {//发送物品仓库添加物品表单
    pl.sendForm(createGlobalItemStoreAddFm(pl), globalItemStoreAdd);
}

function sendGlobalItemStoreDeleteFm(pl) {//发送物品仓库删除物品表单\导入物品仓库到优先组中
    let plData = getPlayerData(pl);
    if (plData && plData["itemStore"]) {
        pl.sendForm(createGlobalItemStoreDeleteFm(pl, plData["itemStore"]), isPersonalGlobalType(pl) ? importItemFromGlobal : globalItemStoreDeleteFm);
    } else {
        sendErrorFmToPl(pl, "物品仓库数据加载异常!");
    }
}

function sendGlobalItemStoreViewFm(pl) {//发送物品仓库查看物品表单
    let plData = getPlayerData(pl);
    if (plData && plData["itemStore"]) {
        pl.sendForm(createGlobalItemStoreViewFm(plData["itemStore"]), (pl, id) => {
            sendGlobalItemStoreFm(pl)
        });
    } else {
        sendErrorFmToPl(pl, "物品仓库数据加载异常!");
    }
}

function sendGroupMenuFm(pl) {//发送优先组配置内菜单
    if (!Global[pl.xuid].globalGroupName)
        sendErrorFmToPl(pl, "表单通信异常!");
    else
        pl.sendForm(createGroupMenuFm(pl), groupMenuChoose);
}

function sendAddGroupFm(pl) {//发送创建配置的表单
    pl.sendForm(createAddGroupFm("创建配置"), addGroupByName);
}

function sendDeleteGroupFm(pl) {//向玩家发送删除配置的表单
    let groupNameList = getGroupKeysFromPlayer(pl);
    if (groupNameList) {
        pl.sendForm(createDeleteGroupFm(groupNameList), deleteGroup);
    } else {
        sendErrorFmToPl(pl, "玩家配置信息加载错误!");
    }
}

function sendUpdateGroupFm(pl) {//向玩家发送修改配置的表单
    let plData = getPlayerData(pl);
    let group = plData["groups"][Global[pl.xuid].globalGroupName];
    if (group) {
        pl.sendForm(createUpdateGroupFm(pl, group), updateGroup);
    }
}

function sendDeleteGroupItemFm(pl) {//优先组配置内删除物品
    let plData = getPlayerData(pl);
    let store = plData["itemStore"];
    let list = plData["groups"][Global[pl.xuid].globalGroupName]["itemPriority"];
    if (plData && store && list) {
        pl.sendForm(createDeleteGroupItemFm(list, store), deleteGroupItem);
    }
}

function sendGroupItemView(pl) {//优先组配置内查看物品
    let cnList = getGroupItemCnNameList(pl, Global[pl.xuid].globalGroupName);
    if (cnList) {
        let content = `当前配置内共有${cnList.length}个物品:\n`;
        cnList.forEach((name) => {
            content += name + " , ";
        });
        sendInfoFmToPl(pl, content, (pl, id) => {
            sendGroupMenuFm(pl)
        });
    } else {
        sendErrorFmToPl(pl, "物品信息加载异常!");
    }
}

function sendGroupAddItemFm(pl) {//优先组配置内添加物品
    pl.sendForm(createAddGroupItemFm(), addGroupItem);
}

function sendGroupAddItemFromGlobal(pl) {//从仓库导入物品到优先组配置中
    sendGlobalItemStoreDeleteFm(pl);
}

function sendConfirmFmToPl(pl, msg, callback) {//发送一个警告确认表单
    pl.sendModalForm("§l§4警告", msg, "确定", "取消", callback);
}

function sendChooseSortGroupFm(pl) {
    pl.sendForm(createChooseSortGroupFm(pl), chooseSortGroup);
}

function sendErrorFmToPl(pl, msg) {//向玩家发送一个错误窗口,关闭后直接退出所有表单
    let fm = mc.newSimpleForm();
    fm = fm.setTitle("§l§4错误窗口");
    fm = fm.setContent(`§4${msg}`);
    pl.sendForm(fm, () => {
    });
}

function sendInfoFmToPl(pl, msg, backMethod) {//向玩家发送一个提示窗口,关闭后返回上一级表单
    let fm = mc.newSimpleForm();
    fm = fm.setTitle("§l提示窗口");
    fm = fm.setContent(`${msg}`);
    pl.sendForm(fm, (pl, id) => {
        backMethod(pl);
    });
}

/**
 *@description 表单回调函数
 */

function MenuChoose(pl, id) {//主菜单处理
    switch (id) {
        case 0: {//个人配置
            Global[pl.xuid].type = "personal";//全局变量配置
            sendPersonalConfigFm(pl);
        }
            break;
        case 1: {//背包整理
            Global[pl.xuid].type = undefined;
            sendChooseSortGroupFm(pl);
        }
            break;
        // // case 2: {//箱子整理
        // //
        // // }
        //     break;
        case 2: {//物品仓库
            Global[pl.xuid].type = "global";//全局变量配置
            sendGlobalItemStoreFm(pl);
        }
            break;
    }
}

function personalConfigChoose(pl, id) {//个人配置菜单处理
    if (isNotNull(id)) {
        let group = getGroupById(pl, id);
        if (group) {
            if (group.data) {
                Global[pl.xuid].globalGroupId = id;
                Global[pl.xuid].globalGroupName = group.name;
                sendGroupMenuFm(pl);//配置内菜单
            } else if (group.name === "创建配置") {//创建配置
                sendAddGroupFm(pl);
            } else if (group.name === "删除配置") {//删除配置
                sendDeleteGroupFm(pl);
            }
        } else {
            sendErrorFmToPl(pl, "玩家配置信息加载错误!");
        }
    } else {
        sendMainMenuFm(pl);
    }
}

function globalItemStoreMenuChoose(pl, id) {//物品仓库菜单处理
    if (isNotNull(id)) {
        switch (id) {
            case 0: {//添加物品
                sendGlobalItemStoreAddFm(pl);
            }
                break;
            case 1: {//删除物品
                sendGlobalItemStoreDeleteFm(pl);
            }
                break;
            case 2: {//查看物品
                sendGlobalItemStoreViewFm(pl);
            }
        }
    } else {
        sendMainMenuFm(pl);
    }
}

function globalItemStoreAdd(pl, data) {//物品仓库添加物品处理/优先组配置添加策略
    let plData = getPlayerData(pl);
    if (isNotNull(data) && plData) {
        let itemName = data[0];
        if (itemName !== "") {//玩家输入不为空
            let hand = pl.getHand();
            if (hand.name !== "") {//物品不为空
                let keyList = Object.keys(plData["itemStore"]);
                if (keyList.indexOf(hand.type) === -1) {//该物品不存在
                    plData["itemStore"][hand.type] = {cn: itemName, type: hand.type};
                    if (isPersonalGlobalType(pl) && isNotNull(Global[pl.xuid].globalGroupId) && isNotNull(Global[pl.xuid].globalGroupName)) {//如果为添加物品模式为个人配置模式则同时将物品添加到玩家优先组中
                        plData["groups"][Global[pl.xuid].globalGroupName]["itemPriority"].push(hand.type);
                    }
                    if (setPlayerData(pl, plData)) {//添加成功
                        isPersonalGlobalType(pl) ? sendGroupMenuFm(pl) : sendGlobalItemStoreFm(pl);
                    } else {
                        sendErrorFmToPl(pl, "物品添加失败:数据读取异常!");
                    }
                } else {//物品已存在
                    sendInfoFmToPl(pl, "该物品种类仓库中已存在,附魔物品算作同一类,改名物品则不算", isPersonalGlobalType(pl) ? sendGroupMenuFm : sendGlobalItemStoreFm);
                }
            } else {
                sendErrorFmToPl(pl, "当前手中没有物品!");
            }
        } else {
            sendGlobalItemStoreAddFm(pl);//输入为空时持续弹出输入框
        }
    } else {
        isPersonalGlobalType(pl) ? sendGroupMenuFm(pl) : sendGlobalItemStoreFm(pl);
    }
}

function globalItemStoreDeleteFm(pl, data) {//物品仓库删除物品处理
    if (isNotNull(data)) {
        sendConfirmFmToPl(pl, "确认删除这些物品?此处删除会同步到所有配置组!", (pl, res) => {
            if (res) {//确认
                let plData = getPlayerData(pl);
                let store = plData["itemStore"];
                let keyList = Object.keys(store);
                let deleteList=[];
                if (isNotNull(data) && isNotNull(store) && isNotNull(keyList)) {
                    for (let i = 0; i < data.length; i++) {
                        if (data[i]) {
                            deleteList.push(keyList[i]);
                            delete store[keyList[i]];
                        }
                    }

                    plData["itemStore"] = store;
                    plData=syncDeleteFromGlobal(plData,deleteList);

                    if (setPlayerData(pl, plData)) {
                        sendGlobalItemStoreFm(pl);
                    } else {
                        sendErrorFmToPl(pl, "删除失败:数据文件加载异常!");
                    }
                } else {
                    sendErrorFmToPl(pl, "删除失败:数据文件加载异常!");
                }
            } else {//取消
                sendGlobalItemStoreDeleteFm(pl);
            }
        })
    } else {
        sendGlobalItemStoreFm(pl);
    }
}

function syncDeleteFromGlobal(plData,deleteList){//同步仓库中删除的物品
    let groups=plData["groups"];
    let keyList=Object.keys(groups);
    for(let i=0;i<keyList.length;i++){//每一个配置组中都删除
        let group=groups[keyList[i]];
        let itemList=group["itemPriority"];

        if (!group||!itemList)
            return null;

        for(let j=0;j<deleteList.length;j++){//标记要删除的元素
            let index=itemList.indexOf(deleteList[j]);
            if (index!==-1){
                itemList[index]=undefined;
            }
        }
        let count = itemList.length;//反向遍历循环删除数组中的元素
        while (count--) {
            if (itemList[count] === undefined) {
                itemList.splice(count, 1);
            }
        }
    }
    return plData;
}

function addGroupByName(pl, data) {//玩家新增一个优先组
    let plData = getPlayerData(pl);
    if (plData && plData["groups"]) {
        if (data) {//若玩家填写了数据
            let groupName = data[0];
            let size = getGroupKeysFromPlayer(pl).length;
            let max=getConfig()["priorityGroupMAX"];
            if (size>=max){//数量超标
                sendConfirmFmToPl(pl,"最多拥有"+max+"个配置组",sendPersonalConfigFm);
                return;
            }
            if (groupName !== "") {
                plData["groups"][groupName] = getDefaultGroup(groupName);
            } else {
                let groupName = `配置-${++size}`;
                plData["groups"][groupName] = getDefaultGroup(groupName);
            }
            if (!setPlayerData(pl, plData))//将更新的玩家数据写入文件
                sendErrorFmToPl(pl, "创建配置失败:数据文件加载异常!");
        }
        //无论玩家是否填写了优先组名称或者取消了表单
        sendPersonalConfigFm(pl);
    }
}

function deleteGroup(pl, data) {//删除优先组
    if (isNotNull(data)) {
        sendConfirmFmToPl(pl, "确认删除?", (pl, result) => {
            if (result) {//确认
                let groupsNameList = getGroupKeysFromPlayer(pl);
                let plData = getPlayerData(pl);
                if (data && groupsNameList && plData["groups"]) {
                    let groups = plData["groups"];
                    for (let i = 1; i < data.length; i++) {
                        if (data[i]) {
                            delete groups[groupsNameList[i - 1]];
                        }
                    }
                    setPlayerData(pl, plData);
                }
                sendPersonalConfigFm(pl);
            } else {//取消
                sendPersonalConfigFm(pl);
            }
        })
    }else {
        sendPersonalConfigFm(pl);
    }
}

function groupMenuChoose(pl, id) {//配置内菜单处理
    if (isNotNull(id)) {
        switch (id) {
            case 0: {//修改配置
                sendUpdateGroupFm(pl);
            }
                break;
            case 1: {//添加物品
                sendGroupAddItemFm(pl);
            }
                break;
            case 2: {//删除物品
                sendDeleteGroupItemFm(pl);
            }
                break;
            case 3: {//查看物品
                sendGroupItemView(pl);
            }
                break;
        }
    } else {
        sendPersonalConfigFm(pl);
    }
}

function updateGroup(pl, data) {//修改优先组配置
    if (isNotNull(data)) {
        sendConfirmFmToPl(pl, `确认修改${Global[pl.xuid].globalGroupName}?`, (pl, res) => {
            if (res) {
                let plData = getPlayerData(pl);
                let group = plData["groups"][Global[pl.xuid].globalGroupName];
                let itemList = group["itemPriority"];
                if (plData && group && itemList) {
                    for (let i = 2; i < data.length; i++) {
                        if (data.lastIndexOf(data[i]) !== i) {
                            sendInfoFmToPl(pl, "同一个物品不能拥有多个优先级!", (pl, id) => {
                                sendUpdateGroupFm(pl)
                            })
                            return;
                        }
                    }
                    group["autoStack"] = data[0];
                    group["mainInventory"] = data[1];
                    let cloneList = [...itemList];
                    for (let i = 2; i < data.length; i++) {
                        let j = i - 2;
                        let k = data[i];
                        if (j !== k)
                            itemList[j] = cloneList[k];
                    }
                    if (setPlayerData(pl, plData)) {
                        sendGroupMenuFm(pl);
                    } else {
                        sendErrorFmToPl(pl, "修改失败:数据文件加载异常！");
                    }
                } else {
                    sendErrorFmToPl(pl, "配置修改失败,数据加载异常!");
                }
            } else {
                sendUpdateGroupFm(pl);
            }
        })
    } else {
        sendGroupMenuFm(pl);
    }
}


function deleteGroupItem(pl, data) {//删除优先组物品
    if (isNotNull(data)) {
        sendConfirmFmToPl(pl, "确认删除这些物品?此操作不会同步至物品仓库!", () => {
            let plData = getPlayerData(pl);
            let itemList = plData["groups"][Global[pl.xuid].globalGroupName]["itemPriority"];
            if (plData&&itemList){
                for (let i = 0; i < data.length; i++) {
                    if (data[i]) {
                        itemList[i] = undefined;
                    }
                }
                let i = itemList.length;//反向遍历循环删除数组中的元素
                while (i--) {
                    if (itemList[i] === undefined) {
                        itemList.splice(i, 1);
                    }
                }
            }
            if (setPlayerData(pl, plData)) {
                sendGroupMenuFm(pl);
            } else {
                sendErrorFmToPl(pl, "删除失败:数据文件加载异常!");
            }
        });
    } else {
        sendDeleteGroupItemFm(pl);
    }
}

function importItemFromGlobal(pl, data) {//从仓库导入物品

    if (isNotNull(data)) {
        sendConfirmFmToPl(pl, `确认将这些物品导入至${Global[pl.xuid].globalGroupName}?`, (pl, res) => {
            let plData = getPlayerData(pl);
            let store = plData["itemStore"];
            let keyList = Object.keys(store);
            let groupItem = plData["groups"][Global[pl.xuid].globalGroupName]["itemPriority"];
            if (!(plData && store && keyList && groupItem)) {
                sendErrorFmToPl(pl, "仓库数据加载错误!");
                return;
            }
            if (res) {
                for (let i = 0; i < data.length; i++) {
                    if (data[i]) {
                        let item = keyList[i];
                        if (groupItem.indexOf(item) < 0)
                            groupItem.push(item);
                    }
                }
                if (setPlayerData(pl, plData)) {
                    sendGroupMenuFm(pl);
                } else {
                    sendErrorFmToPl(pl, "导入失败:数据文件加载异常!");
                }
            } else {
                sendGlobalItemStoreDeleteFm(pl);
            }
        })
    } else {
        sendGroupMenuFm(pl);
    }
}

function addGroupItem(pl, id) {//优先组中添加物品
    if (!isNotNull(Global[pl.xuid].globalGroupName) || !isNotNull(Global[pl.xuid].globalGroupId)) {
        sendErrorFmToPl(pl, "表单通信异常!");
        return;
    }

    if (isNotNull(id)) {
        switch (id) {
            case 0: {
                sendGlobalItemStoreAddFm(pl);//从主手中添加物品
            }
                break;
            case 1: {
                sendGroupAddItemFromGlobal(pl);//从仓库中导物品
            }
                break;
        }
    } else {
        sendGroupMenuFm(pl);
    }
}


function chooseSortGroup(pl, data) {
    if (isNotNull(data)) {
        if (isNotNull(data[0])) {
            let plData = getPlayerData(pl);
            let groups = plData["groups"];
            let keyList = Object.keys(groups);
            let sortGroup = groups[keyList[data[0]]];
            if (plData && groups && keyList) {
                if (sortGroup)
                    sortBackPack(pl, sortGroup);
                else
                    sendErrorFmToPl(pl,"至少需要一个配置组!");
            } else {
                sendErrorFmToPl(pl, "整理背包失败:数据文件加载错误!");
            }

        }
    } else {
        sendMainMenuFm(pl);
    }
}

/**
 * @description 核心排序方法
 */

function sortBackPack(pl, sortGroup) {
    let autoStack = sortGroup["autoStack"];
    let sortMainInventory = sortGroup["mainInventory"];
    let priority = sortGroup["itemPriority"];
    SelectSort(pl, autoStack, sortMainInventory ? 0 : 10, priority);
}

function SelectSort(pl, autoStack, startIndex, priority) {//采用选择排序,方便在排序的同时自动堆叠物品,最好情况下14ms,最差情况下60ms,平均耗时27ms,在数据量很小的情况下,快排和归并的效率并不会高多少，反而占用更多内存。
    let ct = pl.getInventory();
    let size = ct.size;
    if (priority) {
        let start = Date.now();
        for (let i = startIndex; i < size; i++) {
            let index = i;
            for (let j = i + 1; j < size; j++) {
                let res = compareItem(j, index, ct, priority);
                if (res > 0)
                    index = j;
                else if (res === 0 && autoStack)
                    itemStack(index, j, ct);
            }
            if (index !== i)
                swapItem(ct, index, i);
        }
        let dur = Date.now() - start;
        pl.tell("§l§6[背包整理] §r§a本次整理花费了"+dur+"毫秒",0);
        pl.refreshItems();
    } else {
        deBug("配置文件加载出错!");
    }
}


/**
 * @description 物品堆叠
 */
function itemStack(i, j, ct) {//物品堆叠
    let itemI = getItem(i, ct);
    let itemJ = getItem(j, ct);
    let typeI = itemI.type;
    let typeJ = itemJ.type;
    if (typeJ && typeI && typeI === typeJ) {
        let max = stackConfirm(typeI);
        if (max > 1) {//小于等于1无法堆叠
            let countI = itemI.count;
            let countJ = itemJ.count;
            if (countJ + countI <= max) {
                changeItemCountByNbt(itemI, (countJ + countI));
                itemJ.setNull();
            } else {
                changeItemCountByNbt(itemI, max);
                changeItemCountByNbt(itemJ, (countJ + countI - max));
            }
        }
    }
}

function changeItemCountByNbt(item, count) {//通过nbt来修改物品数量
    let nbt = item.getNbt();
    item.setNbt(nbt.setByte("Count", count));
}

function stackConfirm(type) {//物品堆叠确认 1为无法堆叠,16为只能堆叠16个,64为能堆叠64个
    let stackLimit = load(configFile)["stackLimit"];
    if (stackLimit !== null) {
        if (isUnableToStack(type, stackLimit))
            return 1;
        if (isAbleToStack16(type, stackLimit))
            return 16;
        return 64;
    }
    return null;
}

function isUnableToStack(type, sl) {//物品是否可以堆叠
    let unStackClassList = sl["unStackClass"];
    for (let i = 0; i < unStackClassList.length; i++)
        if (type.includes(unStackClassList[i]))//是否为某个不可堆叠的大类
            return true;
    return sl["unStackItems"].indexOf(type) !== -1;//是否为某个不可堆叠的物品
}

function isAbleToStack16(type, sl) {//物品是否只能堆叠16个
    return sl["Stack16Items"].indexOf(type) !== -1;
}

/**
 * @description 物品优先顺序的比较
 */

function compareItem(i, j, ct, priority) {//根据优先组来确定排序顺序
    let itemI = getItem(i, ct);
    let itemJ = getItem(j, ct);
    let nameI = itemI.type;
    let nameJ = itemJ.type;
    let indexI = priority.indexOf(nameI);
    let indexJ = priority.indexOf(nameJ);
    if (indexI < 0 && indexJ < 0)//若两个物品都不存在于优先组中，则根据字符串来确定大小
        return compare(nameI, nameJ);
    else if (indexJ >= 0 && indexI >= 0) {//若两个物品都存在于优先组中,则
        let res = compareReverse(indexI, indexJ);
        if (res === 0) {//如果两个物品种类相同,则比较sNbt字符串的长度，理论上来说附魔越多sNbt字符串越长。
            let sNbtI = itemI.getNbt().toString();
            let sNbtJ = itemJ.getNbt().toString();
            return compare(sNbtI.length, sNbtJ.length);
        } else {
            return res;
        }
    } else {
        return compare(indexI, indexJ);
    }
}

function getItem(index, ct) {
    if (index >= 0 && index < ct.size)
        return ct.getItem(index);
    return null;
}

function compareReverse(i, j) {
    if (i < j)
        return 1;
    else if (j < i)
        return -1;
    else
        return 0;
}

function compare(i, j) {
    if (i > j)
        return 1;
    else if (j > i)
        return -1;
    else
        return 0;
}

function swapItem(ct, i, j) {
    let NBTi = ct.getItem(i).getNbt();
    let NBTj = ct.getItem(j).getNbt();
    ct.setItem(i, mc.newItem(NBTj));
    ct.setItem(j, mc.newItem(NBTi));
}

/**
 * @description 玩家数据操作
 */

function getConfig(){
    return load(configFile);
}

function getDataFile() {//获取所有玩家的数据文件
    let data = load(dataFile);
    return data ? data : null;
}

function setPlayerData(pl, data) {//设置一个玩家的数据
    let Data = getDataFile();
    if (Data && data) {
        Data[pl.xuid] = data;
        save(dataFile, Data);
        return true
    }
    return false;
}

function getPlayerData(pl) {//获取一个玩家的数据
    let plData = load(dataFile);
    if (pl && plData)
        return plData[pl.xuid];
    return null;
}

function getGroupById(pl, id) {//通过控件id获取玩家的优先组配置
    let groups = getPlayerData(pl)["groups"];
    if (groups && isNotNull(id)) {
        let keyList = Object.keys(groups);
        if (id < keyList.length)
            return {name: keyList[id], data: groups[keyList[id]]};
        else if (id === keyList.length)
            return {name: "创建配置", data: null};
        else
            return {name: "删除配置", data: null};
    }
    return null;
}

function getGroupKeysFromPlayer(pl) {//获取一个玩家已拥有优先组的数量
    let plData = getPlayerData(pl);
    if (plData && plData["groups"]) {
        return Object.keys(plData["groups"]);
    }
    return null;
}

function getGroupItemCnNameList(pl, groupName) {//获取优先组内物品的中文列表
    let plData = getPlayerData(pl);
    let store = plData["itemStore"];
    let list = plData["groups"][groupName]["itemPriority"];
    if (plData && store && list) {
        let cnList = [];
        list.forEach((key) => {
            cnList.push(store[key]["cn"]);
        })
        return cnList;
    }
    return null;
}

function getItemStoreCnNameList(store) {//获取仓库物品的中文列表
    let keys = Object.keys(store);
    let list = [];
    keys.forEach((key) => {
        list.push(store[key]["cn"]);
    })
    return list;
}

function getDefaultGroup(name) {//获取默认优先组的数据
    return {
        "name": name,
        "autoStack": true,
        "mainInventory": false,
        "itemPriority": [],
    }
}

function initNewPlayer(pl) {//初始化一个玩家的数据
    let plData = load(dataFile);
    let defaultCfg = load(configFile)["defaultConfig"];
    if (pl && plData && defaultCfg) {
        plData[pl.xuid] = defaultCfg;
        save(dataFile, plData);
    }
}

/**
 * @description 日志调试
 */
function deBug(msg) {
    mc.broadcast(`§l[MINECRAFT]§r §4${msg}`);
}

/**
 * @description 工具
 */

function isNotNull(obj) {//判断一个对象是否为空
    return obj !== null && obj !== undefined;
}

function isPersonalGlobalType(pl) {//当前玩家是否为个人配置模式
    return Global[pl.xuid].type === "personal";
}


/**
 * @description 主方法
 */

function main(pl, args) {
    let plData = load(dataFile);
    if (pl && plData) {
        if (!getPlayerData(pl))
            initNewPlayer(pl);
        Global[pl.xuid] = {};
        sendMainMenuFm(pl);
    }
}

/**
 * @description 玩家命令注册
 */
mc.regPlayerCmd("sort", "整理背包", main);

init();